using System;
using System.Xml;

namespace Google.Apps.Provisioning
{
    /// <summary>
    /// Encapsulates a generic success or failure response from Google's Provisioning API.
    /// </summary>
    public class ProvisioningResponse
    {
        private const string FailureStatusCode = "Failure(2001)";
        private const string SuccessStatusCode = "Success(2000)";

        private string status;
        private string reason;
        private string extendedMessage;
        private string result;

        /// <summary>
        /// The status of the operation, either "Success(2000)" for a success, or "Failure(2001)" for a 
        /// failure.  For convenience, callers may use the IsSuccess() and IsFailure() methods to see
        /// if the operation succeeded.
        /// </summary>
        public string Status
        {
            get { return status; }
        }

        /// <summary>
        /// Populated for failures only.  Includes the reason for the failure, for example
        /// "UserDoesNotExist(1009)".  Please see refer to
        /// <a href="http://code.google.com/apis/apps-for-your-domain/google_apps_provisioning_api_v1.0_reference.html#google_apps_response_tag_reason">Google's online documentation</a> 
        /// for a complete list of failure codes.
        /// </summary>
        public string Reason
        {
            get { return reason; }
        }

        /// <summary>
        /// May contain extended information on why an API request failed to execute.
        /// </summary>
        public string ExtendedMessage
        {
            get { return extendedMessage; }
        }

        /// <summary>
        /// May contain versioning information about the API.
        /// </summary>
        public string Result
        {
            get { return result; }
        }

        public ProvisioningResponse( string responseXml )
        {
            ParseResponse( responseXml );
        }

        private void ParseResponse( string responseXml )
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml( responseXml );

            XmlNamespaceManager ns = new XmlNamespaceManager( doc.NameTable );
            ns.AddNamespace( "hs", "google:accounts:rest:protocol" );

            status = doc.SelectSingleNode( "hs:rest/hs:status", ns ).InnerText;
            reason = doc.SelectSingleNode( "hs:rest/hs:reason", ns ).InnerText;
            extendedMessage = doc.SelectSingleNode( "hs:rest/hs:extendedMessage", ns ).InnerText;
            result = doc.SelectSingleNode( "hs:rest/hs:result", ns ).InnerText;
        }

        /// <summary>
        /// Determines if the operation succeeded.  Note: it can be assumed that if IsSuccess() returns
        /// true, then IsFailure() will return false.
        /// </summary>
        public bool IsSuccess()
        {
            return ( status == SuccessStatusCode );
        }
        
        /// <summary>
        /// Determines if the operation failed.  Note: it can be assumed that if IsFailure() returns 
        /// true, then IsSuccess() will return false.
        /// </summary>
        public bool IsFailure()
        {
            return ( status == FailureStatusCode );
        }

        internal void Debug()
        {
            Console.Out.WriteLine( "Status=" + Status );

            if ( IsFailure() )
            {
                Console.Out.WriteLine( "Reason=" + Reason );
                Console.Out.WriteLine( "ExtendedMessage=" + ExtendedMessage );
                Console.Out.WriteLine( "Result=" + Result );
            }
        }
    }
}
